<?php

namespace StudyBuddy;

/**
 * Class
 * methods common to external authentication
 * like Signin with Twitter, Facebook connect, Google friend Connect, etc.
 *
 * All external auth have this in common:
 * check if user already exists with the given external auth type and id
 * (for example with twitter ID for Twitter user, or with GFC id for
 * Google Friend connect user)
 *
 * If exists, then create User object based on given type/id
 * This is specific to the external auth type and defined in sub-class
 * Then addArray of fresh data that we have just received from external
 * source and then save the data if necessary (if there are any changes, then save
 * the USERS table and also to table specific to external auth provider like
 * to USERS_TWITTER or USERS_GFC table
 *
 * Always send the uid cookie so that external-based auth users
 * will always have auto-login set to true.
 *
 * Post onUserUpdate event at the end of process if any changes has been made
 * to user data
 *
 * After creating/updating the oViewer object login the user
 *
 * If used is not found for this provider/id then create new user
 * first create record in USERS table
 * then using the id from USERS create record in specific auth provider table
 * for example in USERS_TWITTER or USERS_GFC
 *
 * After new user is create post onNewUser event, also login the new user
 * and set uid cookie
 *
 * @todo we may add extra method so that IF user is new to us,
 * and is posted by AJAX then we send back special html of json object
 * so that a popup will be generated asking user to complete one last step:
 * provide an email address and possibly pick a username in case we have
 * a name collision or in case username is no provided by auth provider
 * like Facebook or GFC don't seem to provide username at all
 * we will tell user that they need to confirm their membership by
 * following special account activation link that we will email to them.
 * this is standard.
 * That prompt will send data to us via AJAX and will have a real time email
 * validation progress bar so the receiving php script will do the usual sleep(5) 4 times
 * and keep checking bounces.
 *
 */
class ExternalAuth extends StudyBuddyObject {

    /**
     * Constructor
     * @param Registry $oRegistry
     */
    protected function __construct(Registry $oRegistry) {

        $this->oRegistry = $oRegistry;
    }

    /**
     * Checks in username of twitter user
     * already exists in our regular USERS table
     * and if it does then prepends the @ to the username
     * otherwise returns twitter username
     *
     * The result is that we will use the value of
     * Twitter username as our username OR the @username
     * if username is already taken
     *
     * @todo change this to use MONGO USERS and use something like
     * $any
     *
     * @return string the value of username that will
     * be used as our own username
     *
     */
    public function makeUsername($displayName) {
        d('going to auto_create username based on displayName: ' . $displayName);

        /**
         * Make 100% sure that displayName is in UTF8 encoding
         */
        $displayName = Utf8String::factory($displayName)->valueOf();

        $coll = $this->oRegistry->Mongo->USERS;
        $res = null;

        $username = null;
        $aUsernames = array(
            preg_replace('/\s+/', '_', $displayName),
            preg_replace('/\s+/', '', $displayName),
            preg_replace('/\s+/', '.', $displayName),
            preg_replace('/\s+/', '-', $displayName)
        );

        $aUsernames = \array_unique($aUsernames);

        d('$aUsernames: ' . print_r($aUsernames, 1));

        for ($i = 0; $i < count($aUsernames); $i++) {
            $name = \mb_strtolower($aUsernames[$i], 'utf-8');

            $res = $coll->findOne(array('username_lc' => $name));
            d('$res: ' . $res);
            if (empty($res)) {
                $username = $aUsernames[$i];
                break;
            }
        }

        /**
         * If still could not find username then
         * use brute force and try appending numbers
         * to username untill succeed
         */
        if (null === $username) {
            $i = 1;
            do {
                $name = \mb_strtolower($aUsernames[0], 'utf-8') . $i;
                $res = $coll->findOne(array('username_lc' => $name));
                if (empty($res)) {
                    $username = $aUsernames[0] . $i;
                }
                d('$res: ' . $res);
            } while (null === $username);
        }

        return $username;
    }

}
